#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <poll.h>
#include <signal.h>


void sig_handler(int signum, siginfo_t *siginfo, void *p)
{
	if(signum == SIGIO)
	{
		printf("receive SIGIO\n");
		if(siginfo->si_band & POLLIN)
		{
			//设备有数据可读
			printf("fifo is not empty\n");
		}
		if(siginfo->si_band & POLLOUT)
		{
			//设备可以写入数据
			printf("fifo is not full\n");
		}
	}
}

int main(int argc, char *argv[])
{
	int fd;
	int flag;
	struct sigaction act;

	/* 1、注册信号处理函数 */
	if(sigaction(SIGIO, NULL, &act) == -1)	//获取之前的信号处理方式
	{
		perror("error");
		return -1;
	}
	sigemptyset(&act.sa_mask);		//清空信号集
	sigaddset(&act.sa_mask, SIGIO);	//添加SIGIO到信号集，处理过程中要屏蔽SIGIO
	act.sa_sigaction = sig_handler;	//信号处理函数
	act.sa_flags = SA_SIGINFO;		//使用sa_sigaction的信号处理函数
	if(sigaction(SIGIO, &act, NULL) == -1)	//设置信号处理方式
	{
		perror("error");
		return -1;
	}
	/* 2、打开设备文件 */
	fd = open("/dev/signal", O_RDWR|O_NONBLOCK);
	if(fd == -1)
	{
		perror("error");
		return -1;
	}
	/* 3、设置在此文件描述符上接收信号的进程标识 */
	if(fcntl(fd, F_SETOWN, getpid()) == -1)
	{
		perror("error");
		close(fd);
		return -1;
	}
	/* 4、设置标识输入输出可进行的信号 */
	if(fcntl(fd, F_SETSIG, SIGIO) == -1)
	{
		perror("error");
		close(fd);
		return -1;
	}
	/* 5、设置文件的FASYNC标志 */
	flag = fcntl(fd, F_GETFL);
	if(flag == -1)
	{
		perror("error");
		close(fd);
		return -1;
	}
	if(fcntl(fd, F_SETFL, flag|FASYNC) == -1)
	{
		perror("error");
		close(fd);
		return -1;
	}
	while(1)
	{
		sleep(100);
	}
}
